<!-- 
  浮动粒子背景组件
  用于在页面中创建动态漂浮的粒子效果，增强视觉体验
  支持自定义粒子数量、大小、速度、颜色等参数
-->

<template>
  <div ref="particlesContainer" class="floating-particles"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from "vue";
import p5 from "p5";

/**
 * 粒子配置接口
 */
interface ParticleConfig {
  /**
   * 粒子数量，控制场景中粒子的密度
   * @default 50
   * @example 30 (稀疏) / 80 (密集)
   */
  particleCount?: number;

  /**
   * 粒子大小范围，控制粒子的最小和最大尺寸
   * @default { min: 2, max: 6 }
   * @example { min: 1, max: 8 } (大小差异明显)
   */
  particleSize?: { min: number; max: number };

  /**
   * 粒子移动速度范围，控制粒子的运动快慢
   * 负值表示反向运动，绝对值越大运动越快
   * @default { min: -0.5, max: 0.5 }
   * @example { min: -1, max: 1 } (快速运动)
   */
  speed?: { min: number; max: number };

  /**
   * 粒子透明度范围，控制粒子的可见程度
   * 范围: 0 (完全透明) ~ 1 (完全不透明)
   * @default { min: 0.1, max: 0.3 }
   * @example { min: 0.05, max: 0.5 } (透明度变化大)
   */
  opacity?: { min: number; max: number };

  /**
   * 粒子颜色，使用RGB颜色模式
   * @default { r: 212, g: 175, b: 55 } (金色)
   * @example { r: 100, g: 200, b: 255 } (蓝色)
   */
  color?: { r: number; g: number; b: number };

  /**
   * 容器元素ID，用于指定粒子画布挂载的父元素
   * 如果未提供，则使用组件内部的默认容器
   * @default undefined (使用组件内部容器)
   */
  containerId?: string;
}

/**
 * 组件属性定义
 * 为每个参数提供默认值，确保组件稳定运行
 */
const props = withDefaults(defineProps<ParticleConfig>(), {
  particleCount: 50,
  particleSize: () => ({ min: 2, max: 6 }),
  speed: () => ({ min: -0.5, max: 0.5 }),
  opacity: () => ({ min: 0.1, max: 0.3 }),
  color: () => ({ r: 212, g: 175, b: 55 }),
  containerId: undefined,
});

/**
 * 粒子容器引用
 * 用于挂载p5.js画布，如果未提供containerId则使用此容器
 */
const particlesContainer = ref<HTMLElement>();

/**
 * p5.js实例引用
 * 用于在组件销毁时正确清理p5.js实例，避免内存泄漏
 */
let p5Instance: p5 | null = null;

/**
 * 创建粒子背景效果
 * 使用p5.js库生成动态漂浮的粒子系统
 * 粒子会在画布边界内反弹，形成自然的漂浮效果
 */
const createParticleBackground = () => {
  // 确定使用哪个容器来挂载画布
  const container = props.containerId ? document.getElementById(props.containerId) : particlesContainer.value;

  if (!container) {
    console.warn("ParticleBackground: 未找到容器元素");
    return;
  }

  const sketch = (p: p5) => {
    /** 存储所有粒子对象的数组 */
    let particles: any[] = [];

    /**
     * p5.js初始化函数
     * 创建画布并初始化粒子系统
     */
    p.setup = () => {
      // 创建全屏画布，覆盖整个容器
      const canvas = p.createCanvas(p.windowWidth, p.windowHeight);
      canvas.parent(container!);

      // 初始化粒子数组
      particles = Array.from({ length: props.particleCount }, () => ({
        // 随机初始位置
        x: p.random(p.width),
        y: p.random(p.height),
        // 随机大小
        size: p.random(props.particleSize.min, props.particleSize.max),
        // 随机速度（包含方向）
        speedX: p.random(props.speed.min, props.speed.max),
        speedY: p.random(props.speed.min, props.speed.max),
        // 随机透明度
        opacity: p.random(props.opacity.min, props.opacity.max),
      }));
    };

    /**
     * p5.js绘制循环（每帧执行）
     * 更新粒子位置并重新绘制
     */
    p.draw = () => {
      // 清除上一帧内容，为绘制新帧做准备
      p.clear();

      // 遍历所有粒子并更新绘制
      particles.forEach((particle) => {
        // 设置粒子颜色和透明度
        p.fill(props.color.r, props.color.g, props.color.b, particle.opacity * 255);
        p.noStroke();

        // 绘制圆形粒子
        p.circle(particle.x, particle.y, particle.size);

        // 更新粒子位置
        particle.x += particle.speedX;
        particle.y += particle.speedY;

        // 边界碰撞检测 - 碰到边界时反转速度方向
        if (particle.x < 0 || particle.x > p.width) particle.speedX *= -1;
        if (particle.y < 0 || particle.y > p.height) particle.speedY *= -1;
      });
    };

    /**
     * 窗口大小改变时的响应函数
     * 重新调整画布大小以适应新窗口尺寸
     */
    p.windowResized = () => {
      p.resizeCanvas(p.windowWidth, p.windowHeight);
    };
  };

  // 创建p5.js实例
  p5Instance = new p5(sketch);
};

/**
 * 组件挂载时创建粒子效果
 */
onMounted(() => {
  // 等待DOM渲染完成后再初始化粒子
  setTimeout(() => {
    createParticleBackground();
  }, 100);
});

/**
 * 组件卸载时清理资源
 * 移除p5.js实例，避免内存泄漏和性能问题
 */
onUnmounted(() => {
  if (p5Instance) {
    p5Instance.remove();
    p5Instance = null;
  }
});
</script>

<style scoped>
/**
 * 粒子容器样式
 * 固定定位覆盖整个视口，置于底层不影响交互
 */
.floating-particles {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  /* 禁止粒子容器接收鼠标事件，确保页面内容可交互 */
  pointer-events: none;
  /* 置于底层，作为背景效果 */
  z-index: -1;
}
</style>
